package com.woniu.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.woniu.entity.Address;
import com.woniu.entity.Book;
import com.woniu.entity.User;
import com.woniu.entity.UserCart;
import com.woniu.entity.dto.UserDTO;
import com.woniu.mapper.BookMapper;
import com.woniu.mapper.UserMapper;
import com.woniu.service.UserService;
import com.woniu.util.JWTUtil;
import com.woniu.util.ResData;
import com.woniu.util.ResEnum;
import com.woniu.util.SecureMD5Util;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BookMapper bookMapper;
    @Autowired
    private StringRedisTemplate redisTemplates;
    @Override
    public ResData<?> login(User user) {
        try {
            User userDB = userMapper.login(user.getAccount());
            if (userDB == null) {
                return new ResData<>().fail(ResEnum.LOGIN_ERROR);
            }
            //为了保证密码安全性，一般要把前端的密码加上 盐值，再进行加密，生成密码放入数据库
            String s = SecureMD5Util.md5Salt(user.getPassword());
            if(!userDB.getPassword().equals(s)){
                return new ResData<>().fail(ResEnum.LOGIN_ERROR);
            }
            Map map = new HashMap();
            map.put("userId",userDB.getId());
            map.put("username",userDB.getNickName());
            String jwt = JWTUtil.createJWT(map);
            //参数3：数值
            //参数4：时间单位
            redisTemplates.opsForValue().set("jwt-"+userDB.getId(),jwt,30, TimeUnit.MINUTES);
            return new ResData<>().ok(new UserDTO(userDB),jwt);
        } catch (Exception e) {
            return new ResData<>().fail(ResEnum.FAIL);
        }
    }

    /**
     * 用户添加购物车
     * 实现步骤
     * 1:根据用户id 和书籍 id 查询是否添加过此书籍
     *     没有添加过，插入一购物车表
     *     有添加过，重新计算购买类和总价格
     * @param userCart
     * @return
     */
    @Override
    public ResData<?> addCart(UserCart userCart,String jwt) {
        try {
            Map userInfo = JWTUtil.getJWTUserInfo(jwt);
            Long userId = (Long) userInfo.get("userId");
            userCart.setUserId(userId.intValue());
            UserCart userCart1 = userMapper.queryUserCartByBookIdAndUserId(userCart);
            //根据书籍ID查最新价格
            Book book = bookMapper.queryBookDetailByBookId(userCart.getBookId());

            UserCart userCart2 = new UserCart();
            userCart2.setUserId(userId.intValue());
            userCart2.setBuyNum(userCart1==null?userCart.getBuyNum():userCart.getBuyNum()+userCart1.getBuyNum());
            userCart2.setBuyPrice(book.getPrice());
            userCart2.setTotalPrice(book.getPrice().multiply(new BigDecimal(userCart2.getBuyNum())));
            userCart2.setBookId(userCart.getBookId());

            if(userCart1==null){
                //新增
                userMapper.insertUserCart(userCart2);
            }else {
                //修改
                userCart2.setId(userCart1.getId());
                userMapper.updateUserCart(userCart2);
            }
            return new ResData<>().ok();
        } catch (Exception e) {
            return new ResData<>().fail(ResEnum.FAIL);
        }
    }

    /**
     * 查询用户购物车、用户收货地址信息
     * @param jwt
     * @return
     */
    @SneakyThrows
    @Override
    public ResData<?> queryUserCart(String jwt) {
        try {
            //查询用户的购物车信息
            Map userInfo = JWTUtil.getJWTUserInfo(jwt);
            Long userId = (Long) userInfo.get("userId");
            List<UserCart> userCarts = userMapper.queryUserCartByUserId(userId.intValue());

            //用户收货地址
            List<Address> addresses = userMapper.queryUserAddressByUserId(userId.intValue());
            Map resultMap = new HashMap();
            resultMap.put("userCarts",userCarts);
            resultMap.put("addresses",addresses);
            return new ResData<>().ok(resultMap);
        } catch (ParseException e) {
            return new ResData<>().fail(ResEnum.FAIL);
        }
    }
}
